
#include "CreatureManager.h"


#include "GameDB.h"
#include "DBManager.h"
#include "DBLoginHandler.h"

extern netServer* gNetServer;
extern dbIDatabase* gDBServer;

CreatureManager* gCreatureManager = F_NULL;
map< fint32 , PetPhotoData > gMapPetPhotoID;

CreatureManager::CreatureManager()
{
	gCreatureManager = this;
}


CreatureManager::~CreatureManager()
{

}


fvoid				CreatureManager::Init()
{
	for ( fint32 i = 0 ; i < PLAYER_CACHE_COUNT ; i++ )
	{
		mPlayerCache[i] = new GamePlayer();
		mFreePlayer.push_back( mPlayerCache[i] );
	}

	for ( fint32 i = 0 ; i < PLAYER_CACHE_COUNT * 0.5 ; i++ )
	{
		mFreeTeamList.push_back( new GameTeam() );
	}
}


fvoid				CreatureManager::Release()
{
	for ( fint32 i = 0 ; i < PLAYER_CACHE_COUNT ; i++ )
	{
		delete mPlayerCache[i];
	}

	delete mThis;
	mThis = F_NULL;
}


GamePlayer*			CreatureManager::CreatPlayer()
{
	if ( mFreePlayer.empty() )
	{
		return F_NULL;
	}

	GamePlayer* player = *mFreePlayer.begin();
	mFreePlayer.erase( mFreePlayer.begin() );

	//init player 
	player->Init();

	return player;
}


GamePlayer*			CreatureManager::GetPlayer( fint32 guid )
{
	GamePlayerMapIter iter = mGamePlayerMap.find(guid);

	if ( iter == mGamePlayerMap.end() )
	{
		//logManager::Print( "GetPlayer( fint32 guid ) Player not found" );

		return F_NULL;
	}
	else
	{
		return iter->second;
	}
}


GamePlayer*			CreatureManager::GetPlayer( netSocket* socket )
{
	GamePlayerSocketsMapIter iter = mGamePlayerSocketsMap.find( socket );

	if ( iter == mGamePlayerSocketsMap.end() )
	{
		//logManager::Print( "GetPlayer( fint32 guid ) Player not found" );

		return F_NULL;
	}
	else
	{
		return iter->second;
	}
}

fvoid				CreatureManager::ReleasePlayer( GamePlayer* player )
{
	GamePlayerMapIter iter = mGamePlayerMap.find( player->GetGUID() );
	if ( iter != mGamePlayerMap.end() )
		mGamePlayerMap.erase( iter );

// 	GamePlayerSocketsMapIter itersocket = mGamePlayerSocketsMap.find( player->GetSocket() );
// 	if ( itersocket != mGamePlayerSocketsMap.end() )
// 		mGamePlayerSocketsMap.erase( itersocket );
}

fvoid				CreatureManager::RemovePlayer( GamePlayer* player )
{
	FreePlayerIter iter = std::find( mFreePlayer.begin() , mFreePlayer.end() , player );
	if ( iter == mFreePlayer.end() )
	{
		mFreePlayer.push_back( player );
	}
}


fbool				CreatureManager::SetGUID( fint32 guid , GamePlayer* player )
{
	if ( mGamePlayerMap.find(guid) == mGamePlayerMap.end() )
	{
		mGamePlayerMap[ guid ] = player;

		player->SetGUID( guid );
		return F_TRUE;
	}
	else
	{
		//logManager::Print( "player set GUID again" );
		return F_FALSE;
	}

}


fbool				CreatureManager::SetSocket( netSocket* socket , GamePlayer* player )
{
	if ( mGamePlayerSocketsMap.find( socket ) == mGamePlayerSocketsMap.end() )
	{
		mGamePlayerSocketsMap[ socket ] = player;

		player->SetSocket( socket );
		return F_TRUE;
	}
	else
	{
		//logManager::Print( "player set socket again" );
		socket->Close();
		return F_FALSE;
	}
}

fvoid				CreatureManager::RemoveSocket( GamePlayer* player  )
{
	netSocket* socket = player->GetSocket();

	if ( socket )
	{
		GamePlayerSocketsMapIter iter = mGamePlayerSocketsMap.find( socket );
		mGamePlayerSocketsMap.erase( iter );
		player->SetSocket( F_NULL );
	}
}

fvoid				CreatureManager::AddMsgToAll( netMsgHead* msg )
{
	GamePlayerMapIter iter = mGamePlayerMap.begin();
	GamePlayerMapIter iterend = mGamePlayerMap.end();

	for ( ; iter != iterend ; ++iter )
	{
		iter->second->GetSocket()->ParkMsg( msg );
	}
}


fvoid				CreatureManager::SendMsgToAll()
{
	GamePlayerMapIter iter = mGamePlayerMap.begin();
	GamePlayerMapIter iterend = mGamePlayerMap.end();

	for ( ; iter != iterend ; ++iter )
	{
		iter->second->GetSocket()->SendMsg();
	}
}


fvoid				CreatureManager::Close()
{
	GamePlayerMapIter iter = mGamePlayerMap.begin();
	GamePlayerMapIter iterend = mGamePlayerMap.end();

	for ( ; iter != iterend ; ++iter )
	{
		GamePetMap& petMap = iter->second->GetPetMap();
		GamePetMapIter iterEnd1 = petMap.end();

		for ( GamePetMapIter iter1 = petMap.begin() ; iter1 != iterEnd1 ; ++iter1 )
		{
			SPRINTF( SQL_BUFFER , SQL_UPDATE_PET.c_str() , iter1->first , iter1->second.GetData().Name , DBManager::GetPetDBData( &(iter1->second) ) );
			SQL_BUFFER[ MAX_SQL_BUFFER - 1 ] = '\0';
			gDBServer->ExecuteAsyncSQL( SQL_BUFFER , iter->second , DB_Update_Pet );
		}

		SPRINTF( SQL_BUFFER , SQL_UPDATE_QUITGAME.c_str() , iter->second->GetGUID() , DBManager::GetPlayerDBData( iter->second ) );
		SQL_BUFFER[ MAX_SQL_BUFFER - 1 ] = '\0';
        
		gDBServer->ExecuteAsyncSQL( SQL_BUFFER , iter->second , DB_Update_QuitGame );
	}
}


fint32				CreatureManager::GetFreePlayerCount()
{
	return (fint32)mFreePlayer.size();
}

fint32				CreatureManager::GetSocketPlayerCount()
{
	return (fint32)mGamePlayerSocketsMap.size();
}

fint32				CreatureManager::GetPlayerCount()
{
	return (fint32)mGamePlayerMap.size();
}

fint32				CreatureManager::GetGuestount()
{
	GamePlayerMapIter iter = mGamePlayerMap.begin();
	GamePlayerMapIter iterend = mGamePlayerMap.end();

	fint32 n = 0;
	for ( ; iter != iterend ; ++iter )
	{
		if ( iter->first >= GUEST_GUID )
		{
			++n;
		}
	}

	return n;
}


// fvoid				CreatureManager::SetUserRoleInfo( fint32 guid , const UserRoleInfo& info )
// {
// 	mUserRoleInfo[ guid ] = info;
// }
// 
// 
// UserRoleInfo&		CreatureManager::GetUserRoleInfo( fint32 guid )
// {
// 	return mUserRoleInfo[ guid ];
// }
















//////////////////////////////////////////////////////////////////////////
// enemy

GameEnemyBase*		CreatureManager::GetEnemyBase( fint32 id )
{
	GameEnemyBaseMapIter iter = mGameEnemyBaseMap.find( id );

	return &iter->second;
}

GameEnemy*			CreatureManager::GetEnemy( fint32 id )
{
	GameEnemyMapIter iter = mGameEnemyMap.find( id );

	return &iter->second;
}

GameEnemyGroup*		CreatureManager::GetEnemyGroup( fint32 id )
{
	GameEnemyGroupMapIter iter = mGameEnemyGroupMap.find( id );

	if ( iter == mGameEnemyGroupMap.end() )
	{
		return F_NULL;
	}

	return &(iter->second);
}


fvoid				CreatureManager::LoadPetPhoto( const fbyte* path )
{
    ptree pt;
    ptree root;
    
    read_xml( path , pt , boost::property_tree::xml_parser::trim_whitespace );
    
    FLOG4( "xml loading. %s" , path );
    
    root = pt.get_child( "root" );
    
    ptree::assoc_iterator iter = root.ordered_begin();
    
    for (  ; iter != root.not_found() ; ++iter )
    {
        ptree n = iter->second;
        
        fint32 id , photo , baseId;
        id = n.get< fint32 >( "<xmlattr>.id" );
        baseId = n.get< fint32 >( "<xmlattr>.baseId" );
        photo = n.get< fint32 >( "<xmlattr>.photo" );
        
        gMapPetPhotoID[ baseId ].photo = photo;
        gMapPetPhotoID[ baseId ].id = id;
    }
    
    FLOG4( "xml loaded. %s" , path );
}


fvoid				CreatureManager::LoadEnemyBase( const fbyte* path )
{
    ptree pt;
    ptree root;
    
    read_xml( path , pt , boost::property_tree::xml_parser::trim_whitespace );
    
    FLOG4( "xml loading. %s" , path );
    
    root = pt.get_child( "root" );
    
    ptree::assoc_iterator iter = root.ordered_begin();
    
    for (  ; iter != root.not_found() ; ++iter )
    {
        ptree n = iter->second;
        
        GameEnemyBase base;
        
        base.levelUpPoint = n.get< freal32 >( "<xmlattr>.levelUpPoint" );
        base.intValue[ GEBIV_ID ] = n.get< fint32 >( "<xmlattr>.id" );
        base.intValue[ GEBIV_ROLE ] = n.get< fint32 >( "<xmlattr>.imgNum" );
        
        base.intValue[ GEBIV_BASEVITALITY ] = n.get< fint32 >( "<xmlattr>.baseVitality" );
        base.intValue[ GEBIV_BASESTRENGTH ] = n.get< fint32 >( "<xmlattr>.baseStrength" );
        base.intValue[ GEBIV_BASETOUGHNESS ] = n.get< fint32 >( "<xmlattr>.baseToughness" );
        base.intValue[ GEBIV_BASEDEXTERITY ] = n.get< fint32 >( "<xmlattr>.baseDexterity" );
        
        base.intValue[ GEBIV_EARTH ] = n.get< fint32 >( "<xmlattr>.earth" );
        base.intValue[ GEBIV_WATER ] = n.get< fint32 >( "<xmlattr>.water" );
        base.intValue[ GEBIV_FIRE ] = n.get< fint32 >( "<xmlattr>.fire" );
        base.intValue[ GEBIV_WIND ] = n.get< fint32 >( "<xmlattr>.wind" );
        
        base.intValue[ GEBIV_INITNUM ] = n.get< fint32 >( "<xmlattr>.initNum" );
        base.intValue[ GEBIV_AI ] = n.get< fint32 >( "<xmlattr>.ai" );
        base.intValue[ GEBIV_GET ] = n.get< fint32 >( "<xmlattr>.get" );
        
        base.intValue[ GEBIV_POISON ] = n.get< fint32 >( "<xmlattr>.poison" );
        base.intValue[ GEBIV_PARALYSIS ] = n.get< fint32 >( "<xmlattr>.paralysis" );
        base.intValue[ GEBIV_SLEEP ] = n.get< fint32 >( "<xmlattr>.sleep" );
        base.intValue[ GEBIV_STONE ] = n.get< fint32 >( "<xmlattr>.stone" );
        base.intValue[ GEBIV_DRUNK ] = n.get< fint32 >( "<xmlattr>.drunk" );
        base.intValue[ GEBIV_CONFUSION ] = n.get< fint32 >( "<xmlattr>.confusion" );
        
        base.intValue[ GEBIV_PETSKILL0 ] = n.get< fint32 >( "<xmlattr>.petSkill0" );
        base.intValue[ GEBIV_PETSKILL1 ] = n.get< fint32 >( "<xmlattr>.petSkill1" );
        base.intValue[ GEBIV_PETSKILL2 ] = n.get< fint32 >( "<xmlattr>.petSkill2" );
        base.intValue[ GEBIV_PETSKILL3 ] = n.get< fint32 >( "<xmlattr>.petSkill3" );
        base.intValue[ GEBIV_PETSKILL4 ] = n.get< fint32 >( "<xmlattr>.petSkill4" );
        base.intValue[ GEBIV_PETSKILL5 ] = n.get< fint32 >( "<xmlattr>.petSkill5" );
        base.intValue[ GEBIV_PETSKILL6 ] = n.get< fint32 >( "<xmlattr>.petSkill6" );
        
        base.intValue[ GEBIV_RARE ] = n.get< fint32 >( "<xmlattr>.rare" );
        base.intValue[ GEBIV_CRITICAL ] = n.get< fint32 >( "<xmlattr>.critical" );
        base.intValue[ GEBIV_COUNTER ] = n.get< fint32 >( "<xmlattr>.counter" );
        base.intValue[ GEBIV_SLOT ] = n.get< fint32 >( "<xmlattr>.slot" );
        base.intValue[ GEBIV_PETFLAG ] = n.get< fint32 >( "<xmlattr>.petFlag" );
        base.intValue[ GEBIV_SIZE ] = n.get< fint32 >( "<xmlattr>.size" );
        
        base.intValue[ GEBIV_LIMITLEVEL ] = n.get< fint32 >( "<xmlattr>.limitLevel" );
        base.intValue[ GEBIV_AMALGAMATION ] = n.get< fint32 >( "<xmlattr>.amalgamation" );
        
        base.intValue[ GEBIV_MATERIAL0 ] = n.get< fint32 >( "<xmlattr>.material0" , 0 );
        base.intValue[ GEBIV_MATERIAL1 ] = n.get< fint32 >( "<xmlattr>.material1" , 0 );
        base.intValue[ GEBIV_MATERIAL2 ] = n.get< fint32 >( "<xmlattr>.material2" , 0 );
        base.intValue[ GEBIV_MATERIAL3 ] = n.get< fint32 >( "<xmlattr>.material3" , 0 );
        base.intValue[ GEBIV_MATERIAL4 ] = n.get< fint32 >( "<xmlattr>.material4" , 0 );
        
        
        mGameEnemyBaseMap[ base.intValue[ GEBIV_ID ] ] = base;
    }
    
    FLOG4( "xml loaded. %s" , path );
}


fvoid				CreatureManager::LoadEnemy( const fbyte* path )
{
   
    ptree pt;
    ptree root;
    
    read_xml( path , pt , boost::property_tree::xml_parser::trim_whitespace );
    
    FLOG4( "xml loading. %s" , path );
    
    root = pt.get_child( "root" );
    
    ptree::assoc_iterator iter = root.ordered_begin();
    
    for (  ; iter != root.not_found() ; ++iter )
    {
        ptree n = iter->second;
        
        GameEnemy enemy;
        
        //strcpy( enemy.name , n.get<string>("<xmlattr>.name").c_str() );
        
        enemy.intValue[ GEIV_ID ] = n.get< fint32 >( "<xmlattr>.id" );
        enemy.intValue[ GEIV_BASEID ] = n.get< fint32 >( "<xmlattr>.baseID" );
        
        enemy.intValue[ GEIV_ATTACK ] = n.get< fint32 >( "<xmlattr>.attack" );
        enemy.intValue[ GEIV_ATTACKTARGET ] = n.get< fint32 >( "<xmlattr>.attackTarget" );
        enemy.intValue[ GEIV_ATTACKAI ] = n.get< fint32 >( "<xmlattr>.attackAI" );
        
        enemy.intValue[ GEIV_DEFENCE ] = n.get< fint32 >( "<xmlattr>.defence" );
        enemy.intValue[ GEIV_MAGIC ] = n.get< fint32 >( "<xmlattr>.magic" );
        enemy.intValue[ GEIV_ESCAPE ] = n.get< fint32 >( "<xmlattr>.escape" );
        
        enemy.intValue[ GEIV_WA0 ] = n.get< fint32 >( "<xmlattr>.wa0" );
        enemy.intValue[ GEIV_WA1 ] = n.get< fint32 >( "<xmlattr>.wa1" );
        enemy.intValue[ GEIV_WA2 ] = n.get< fint32 >( "<xmlattr>.wa2" );
        enemy.intValue[ GEIV_WA3 ] = n.get< fint32 >( "<xmlattr>.wa3" );
        enemy.intValue[ GEIV_WA4 ] = n.get< fint32 >( "<xmlattr>.wa4" );
        enemy.intValue[ GEIV_WA5 ] = n.get< fint32 >( "<xmlattr>.wa5" );
        enemy.intValue[ GEIV_WA6 ] = n.get< fint32 >( "<xmlattr>.wa6" );
        
        enemy.intValue[ GEIV_RN ] = n.get< fint32 >( "<xmlattr>.rn" );
        
        enemy.intValue[ GEIV_LEVELMIN ] = n.get< fint32 >( "<xmlattr>.levelMin" );
        enemy.intValue[ GEIV_LEVELMAX ] = n.get< fint32 >( "<xmlattr>.levelMax" );
        enemy.intValue[ GEIV_LEVELNUMMAX ] = n.get< fint32 >( "<xmlattr>.numMax" );
        enemy.intValue[ GEIV_LEVELNUMMIN ] = n.get< fint32 >( "<xmlattr>.numMin" );
        
        enemy.intValue[ GEIV_FIGHT ] = n.get< fint32 >( "<xmlattr>.fight" );
        enemy.intValue[ GEIV_EXP ] = n.get< fint32 >( "<xmlattr>.exp" );
        enemy.intValue[ GEIV_DP ] = n.get< fint32 >( "<xmlattr>.dp" );
        enemy.intValue[ GEIV_TYPE ] = n.get< fint32 >( "<xmlattr>.type" );
        enemy.intValue[ GEIV_PET ] = n.get< fint32 >( "<xmlattr>.pet" );
        
        enemy.intValue[ GEIV_ITEM0 ] = n.get< fint32 >( "<xmlattr>.item0" );
        enemy.intValue[ GEIV_ITEM1 ] = n.get< fint32 >( "<xmlattr>.item1" );
        enemy.intValue[ GEIV_ITEM2 ] = n.get< fint32 >( "<xmlattr>.item2" );
        enemy.intValue[ GEIV_ITEM3 ] = n.get< fint32 >( "<xmlattr>.item3" );
        enemy.intValue[ GEIV_ITEM4 ] = n.get< fint32 >( "<xmlattr>.item4" );
        enemy.intValue[ GEIV_ITEM5 ] = n.get< fint32 >( "<xmlattr>.item5" );
        enemy.intValue[ GEIV_ITEM6 ] = n.get< fint32 >( "<xmlattr>.item6" );
        enemy.intValue[ GEIV_ITEM7 ] = n.get< fint32 >( "<xmlattr>.item7" );
        enemy.intValue[ GEIV_ITEM8 ] = n.get< fint32 >( "<xmlattr>.item8" );
        enemy.intValue[ GEIV_ITEM9 ] = n.get< fint32 >( "<xmlattr>.item9" );
        
        enemy.intValue[ GEIV_ITEMPRO0 ] = n.get< fint32 >( "<xmlattr>.itemPro0" );
        enemy.intValue[ GEIV_ITEMPRO1 ] = n.get< fint32 >( "<xmlattr>.itemPro1" );
        enemy.intValue[ GEIV_ITEMPRO2 ] = n.get< fint32 >( "<xmlattr>.itemPro2" );
        enemy.intValue[ GEIV_ITEMPRO3 ] = n.get< fint32 >( "<xmlattr>.itemPro3" );
        enemy.intValue[ GEIV_ITEMPRO4 ] = n.get< fint32 >( "<xmlattr>.itemPro4" );
        enemy.intValue[ GEIV_ITEMPRO5 ] = n.get< fint32 >( "<xmlattr>.itemPro5" );
        enemy.intValue[ GEIV_ITEMPRO6 ] = n.get< fint32 >( "<xmlattr>.itemPro6" );
        enemy.intValue[ GEIV_ITEMPRO7 ] = n.get< fint32 >( "<xmlattr>.itemPro7" );
        enemy.intValue[ GEIV_ITEMPRO8 ] = n.get< fint32 >( "<xmlattr>.itemPro8" );
        enemy.intValue[ GEIV_ITEMPRO9 ] = n.get< fint32 >( "<xmlattr>.itemPro9" );
        
        mGameEnemyMap[ enemy.intValue[ GEIV_ID ] ] = enemy;
    }
    
    FLOG4( "xml loaded. %s" , path );
}


fvoid				CreatureManager::LoadEnemyGroup( const fbyte* path )
{
    ptree pt;
    ptree root;
    
    read_xml( path , pt , boost::property_tree::xml_parser::trim_whitespace );
    
    FLOG4( "xml loading. %s" , path );
    
    root = pt.get_child( "root" );
    
    ptree::assoc_iterator iter = root.ordered_begin();
    
    for (  ; iter != root.not_found() ; ++iter )
    {
        ptree n = iter->second;
        
        GameEnemyGroup group;
        
        group.intValue[ GEGIV_ID ] = n.get< fint32 >( "<xmlattr>.id" );
        
        group.intValue[ GEGIV_ITEM0 ] = n.get< fint32 >( "<xmlattr>.item0" );
        group.intValue[ GEGIV_ITEM1 ] = n.get< fint32 >( "<xmlattr>.item1" );
        
        group.intValue[ GEGIV_ENEMY0 ] = n.get< fint32 >( "<xmlattr>.enemy0" );
        group.intValue[ GEGIV_ENEMY1 ] = n.get< fint32 >( "<xmlattr>.enemy1" );
        group.intValue[ GEGIV_ENEMY2 ] = n.get< fint32 >( "<xmlattr>.enemy2" );
        group.intValue[ GEGIV_ENEMY3 ] = n.get< fint32 >( "<xmlattr>.enemy3" );
        group.intValue[ GEGIV_ENEMY4 ] = n.get< fint32 >( "<xmlattr>.enemy4" );
        group.intValue[ GEGIV_ENEMY5 ] = n.get< fint32 >( "<xmlattr>.enemy5" );
        group.intValue[ GEGIV_ENEMY6 ] = n.get< fint32 >( "<xmlattr>.enemy6" );
        group.intValue[ GEGIV_ENEMY7 ] = n.get< fint32 >( "<xmlattr>.enemy7" );
        group.intValue[ GEGIV_ENEMY8 ] = n.get< fint32 >( "<xmlattr>.enemy8" );
        group.intValue[ GEGIV_ENEMY9 ] = n.get< fint32 >( "<xmlattr>.enemy9" );
        
        group.intValue[ GEGIV_ENEMYPRO0 ] = n.get< fint32 >( "<xmlattr>.enemyPro0" );
        group.intValue[ GEGIV_ENEMYPRO1 ] = n.get< fint32 >( "<xmlattr>.enemyPro1" );
        group.intValue[ GEGIV_ENEMYPRO2 ] = n.get< fint32 >( "<xmlattr>.enemyPro2" );
        group.intValue[ GEGIV_ENEMYPRO3 ] = n.get< fint32 >( "<xmlattr>.enemyPro3" );
        group.intValue[ GEGIV_ENEMYPRO4 ] = n.get< fint32 >( "<xmlattr>.enemyPro4" );
        group.intValue[ GEGIV_ENEMYPRO5 ] = n.get< fint32 >( "<xmlattr>.enemyPro5" );
        group.intValue[ GEGIV_ENEMYPRO6 ] = n.get< fint32 >( "<xmlattr>.enemyPro6" );
        group.intValue[ GEGIV_ENEMYPRO7 ] = n.get< fint32 >( "<xmlattr>.enemyPro7" );
        group.intValue[ GEGIV_ENEMYPRO8 ] = n.get< fint32 >( "<xmlattr>.enemyPro8" );
        group.intValue[ GEGIV_ENEMYPRO9 ] = n.get< fint32 >( "<xmlattr>.enemyPro9" );
        
        mGameEnemyGroupMap[ group.intValue[ GEGIV_ID ] ] = group;
    }
    
    FLOG4( "xml loaded. %s" , path );
}


//////////////////////////////////////////////////////////////////////////
// team

GameTeam*			CreatureManager::CreatTeam()
{
	if ( mFreeTeamList.empty() )
	{
		return F_NULL;
	}

	GameTeam* team = *mFreeTeamList.begin();
	mFreeTeamList.erase( mFreeTeamList.begin() );

	return team;
}


fvoid				CreatureManager::RemoveTeam( GameTeam* team )
{
	mFreeTeamList.push_back( team );
}

